﻿/*
 * copyright (c) 2009 hvbird
 *
 * This file is part of tdlib.
 *
 * tdlib is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * tdlib is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 */

using System;
using System.Collections.Generic;
using System.Collections;
using System.Text;
using System.Diagnostics;

namespace TDLib.Web
{
    /// <summary>
    /// web debug class, debugger for production environment
    /// </summary>
    public class WebDebug : IDebuger
    {
        private System.Web.UI.Page m_page = null;
        private System.Web.UI.UserControl m_control = null;
        Stopwatch m_page_sw;
        System.Text.StringBuilder m_sb;
        // save time counter
        Hashtable m_counter;
        private int m_check_status = -1;
        private string m_control_name = "";
        private bool m_iscomment = true;

        /// <summary>
        /// web page debuger
        /// </summary>
        /// <param name="page"></param>
        public WebDebug(System.Web.UI.Page page)
        {
            if (IsDebug())
            {
                m_page_sw = Stopwatch.StartNew();
                m_counter = new Hashtable();
                m_sb = new StringBuilder();
                m_page = page;
                m_page.Init += new EventHandler(m_page_Init);
                m_page.LoadComplete += new EventHandler(m_page_LoadComplete);
            }
        }

        /// <summary>
        /// web usercontrol debuger
        /// </summary>
        /// <param name="control"></param>
        public WebDebug(System.Web.UI.UserControl control)
        {
            if (IsDebug())
            {
                m_page_sw = new Stopwatch();
                m_counter = new Hashtable();
                m_sb = new StringBuilder();
                m_control = control;

                m_control_name = m_control.GetType().ToString();

                m_control.PreRender += new EventHandler(m_control_PreRender);
                m_control.Unload += new EventHandler(m_control_Unload);
            }
        }

        void m_control_Unload(object sender, EventArgs e)
        {
            m_page_sw.Stop();

            // stop all time counter
            foreach (Object obj in m_counter)
            {
                if (obj is Stopwatch)
                {
                    Stopwatch counter = (Stopwatch)obj;
                    counter.Stop();
                }

            }



            if (m_iscomment)
            {
                m_sb.Append(m_control_name + " runtime:" + m_page_sw.ElapsedMilliseconds + "\r\n");
                System.Web.HttpContext.Current.Response.Write("<!-- " + m_sb.ToString() + "\r\n" + DateTime.Now + " -->\r\n");
            }
            else
            {
                m_sb.Append(m_control_name + " runtime:" + m_page_sw.ElapsedMilliseconds + "<br/>");
                System.Web.HttpContext.Current.Response.Write(m_sb.ToString() + "<br/>" + DateTime.Now);
            }
        }


        void m_control_PreRender(object sender, EventArgs e)
        {
            m_page_sw.Start();
        }

        /// <summary>
        /// output debug information
        /// </summary>
        /// <param name="msg"></param>
        public void WriteDebugInfo(string msg)
        {
            if (IsDebug())
            {
                if (m_iscomment)
                {
                    m_sb.Append(msg + "\r\n");
                }
                else
                {
                    m_sb.Append(msg + "<br/>");
                }
            }
        }

        /// <summary>
        /// start a new time counter, notice when the counter name existed, it should be start again.
        /// </summary>
        /// <param name="countername"></param>
        public bool StartCounter(string countername)
        {
            if (IsDebug())
            {
                if(!m_counter.Contains(countername))
                {
                    Stopwatch watch = Stopwatch.StartNew();
                    watch.Start();

                    //添加到队列中
                    m_counter.Add(countername, watch);

                    return true;
                }
                else
                {
                    Stopwatch watch = (Stopwatch)m_counter[countername];

                    if (watch.IsRunning)
                        return false;
                    else
                        watch.Start();

                    return true;
                }
            }

            return false;
        }

        // stop a time counter
        public void EndCounter(string countername)
        {
            if (IsDebug())
            {
                if(m_counter.Contains(countername))
                {
                    Stopwatch watch = (Stopwatch)m_counter[countername];
                    watch.Stop();

                    // output time counter information
                    if (m_control != null)
                    {
                        if (m_iscomment)
                        {
                            m_sb.Append(m_control_name + " " + countername + " runtime:" + watch.ElapsedMilliseconds + "\r\n");
                        }
                        else
                        {
                            m_sb.Append(m_control_name + " " + countername + " runtime:" + watch.ElapsedMilliseconds + "<br/>");
                        }

                    }
                    if (m_page != null)
                    {
                        if (m_iscomment)
                        {
                            m_sb.Append(m_page.Request.Url.AbsolutePath + " " + countername + " runtime:" + watch.ElapsedMilliseconds + "\r\n");
                        }
                        else
                        {
                            m_sb.Append(m_page.Request.Url.AbsolutePath + " " + countername + " runtime:" + watch.ElapsedMilliseconds + "<br/>");
                        }
                    }
                }
            }
        }


        /// <summary>
        /// page(or usercontrol) loading completed
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void m_page_LoadComplete(object sender, EventArgs e)
        {
            m_page_sw.Stop();

            // stop all counter
            foreach (Object obj in m_counter)
            {
                if (obj is Stopwatch)
                {
                    Stopwatch counter = (Stopwatch)obj;
                    counter.Stop();
                }
            }

            if (m_iscomment)
            {
                m_sb.Append(m_page.Request.Url.PathAndQuery + " runtime:" + m_page_sw.ElapsedMilliseconds + "\r\n"+DateTime.Now);
                m_page.Response.Write("<!-- " + m_sb.ToString() + " -->\r\n");
            }
            else
            {
                m_sb.Append(m_page.Request.Url.PathAndQuery + " runtime:" + m_page_sw.ElapsedMilliseconds + "<br/>"+DateTime.Now);
                m_page.Response.Write(m_sb.ToString());
            }
        }

        /// <summary>
        /// page (or usercontrol) initialization
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void m_page_Init(object sender, EventArgs e)
        {
            m_page_sw.Reset();
            m_page_sw.Start();
        }

        public bool IsDebug()
        {
            System.Web.HttpRequest request = System.Web.HttpContext.Current.Request;
            System.Web.HttpResponse response = System.Web.HttpContext.Current.Response;
            bool ret = false;

            if (request == null || response == null)
                return false;

            if (m_check_status>-1)
            {
                if (m_check_status == 0)
                    return false;
                else
                    return true;
            }

            // check whether has a debug flag
            if(request.QueryString["debug"] != null)
            {
                if(request.QueryString["debug"] == "1")
                {
                    ret = true;
                    // save debug flag into cookie
                    System.Web.HttpCookie cookie = new System.Web.HttpCookie("yoka_debug", "1");
                    response.Cookies.Add(cookie);
                }
                else
                {
                    ret = false;
                    // clear coolie information about debug
                    System.Web.HttpCookie cookie = new System.Web.HttpCookie("yoka_debug", "0");
                    cookie.Expires = DateTime.Now.AddDays(-3);
                    response.Cookies.Add(cookie);
                }
            }
            else
            {
                if(request.Cookies["yoka_debug"] !=null)
                {
                    if(request.Cookies["yoka_debug"].Value == "1")
                    {
                        ret = true;
                    }
                }
            }

            if (ret)
                m_check_status = 1;
            else
                m_check_status = 0;

            return ret;
        }
        
        /// <summary>
        /// whether out put debug information as HTML comment
        /// </summary>
        public bool IsComment
        {
            get { return m_iscomment; }
            set { m_iscomment = value; }
        }
    }
}
